#include "Platform/Windows/qnxWindow.h"

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/keycodes.h>

#include <chrono>
#include <ctime>
#include <ratio>

#include <screen/screen.h>

#include <EGL/egl.h>

#include "error.h"
#include <pthread.h>
#include <vector>
#include <map>
#include <unistd.h>

extern "C"
{
#include "waveself.h"
}

using namespace std::chrono;

GLfloat fg_alpha;
GLfloat bg_alpha = 0;
static pthread_t sound_thread;

static std::map<std::string, bool> sounds;
static bool running = true;

// #include "Hazel/Core/Input.h"

// #include "Hazel/Events/ApplicationEvent.h"
// #include "Hazel/Events/MouseEvent.h"
// #include "Hazel/Events/KeyEvent.h"

// #include "Hazel/Renderer/Renderer.h"

// #include "Platform/OpenGL/OpenGLContext.h"

namespace CC
{

	static void *sound_thread_handler(void *data)
	{
		while (running)
		{
			for (std::map<std::string, bool>::iterator iter = sounds.begin(); iter != sounds.end(); ++iter)
			{
				if (iter->second)
				{
					std::string str = iter->first;
					sounds[str] = false;
					char *argv[2] = {"", ""};

					argv[1] = (char *)(str.c_str());
					playMusicQnx(2, argv);
				}
			}
			usleep(10000);
		}

		return NULL;
	}

	struct
	{
		EGLint red_size;
		EGLint green_size;
		EGLint blue_size;
		EGLint alpha_size;
		EGLint samples;
		EGLint config_id;
	} egl_conf_attr = {
		.red_size = EGL_DONT_CARE,
		.green_size = EGL_DONT_CARE,
		.blue_size = EGL_DONT_CARE,
		.alpha_size = EGL_DONT_CARE,
		.samples = EGL_DONT_CARE,
		.config_id = EGL_DONT_CARE,
	};

	EGLConfig choose_config(EGLDisplay egl_disp, const char *str)
	{
		EGLConfig egl_conf = (EGLConfig)0;
		EGLConfig *egl_configs;
		EGLint egl_num_configs;
		EGLint val;
		EGLBoolean rc;
		const char *tok;
		EGLint i;

		if (str != NULL)
		{
			tok = str;
			while (*tok == ' ' || *tok == ',')
			{
				tok++;
			}

			while (*tok != '\0')
			{
				if (strncmp(tok, "rgba8888", strlen("rgba8888")) == 0)
				{
					egl_conf_attr.red_size = 8;
					egl_conf_attr.green_size = 8;
					egl_conf_attr.blue_size = 8;
					egl_conf_attr.alpha_size = 8;
					tok += strlen("rgba8888");
				}
				else if (strncmp(tok, "rgba5551", strlen("rgba5551")) == 0)
				{
					egl_conf_attr.red_size = 5;
					egl_conf_attr.green_size = 5;
					egl_conf_attr.blue_size = 5;
					egl_conf_attr.alpha_size = 1;
					tok += strlen("rgba5551");
				}
				else if (strncmp(tok, "rgba4444", strlen("rgba4444")) == 0)
				{
					egl_conf_attr.red_size = 4;
					egl_conf_attr.green_size = 4;
					egl_conf_attr.blue_size = 4;
					egl_conf_attr.alpha_size = 4;
					tok += strlen("rgba4444");
				}
				else if (strncmp(tok, "rgb565", strlen("rgb565")) == 0)
				{
					egl_conf_attr.red_size = 5;
					egl_conf_attr.green_size = 6;
					egl_conf_attr.blue_size = 5;
					egl_conf_attr.alpha_size = 0;
					tok += strlen("rgb565");
				}
				else if (isdigit(*tok))
				{
					val = atoi(tok);
					while (isdigit(*(++tok)))
						;
					if (*tok == 'x')
					{
						egl_conf_attr.samples = val;
						tok++;
					}
					else
					{
						egl_conf_attr.config_id = val;
					}
				}
				else
				{
					fprintf(stderr, "invalid configuration specifier: ");
					while (*tok != ' ' && *tok != ',' && *tok != '\0')
					{
						fputc(*tok++, stderr);
					}
					fputc('\n', stderr);
				}

				while (*tok == ' ' || *tok == ',')
				{
					tok++;
				}
			}
		}

		rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglGetConfigs");
			return egl_conf;
		}
		if (egl_num_configs == 0)
		{
			fprintf(stderr, "eglGetConfigs: could not find a configuration\n");
			return egl_conf;
		}

		egl_configs = (EGLConfig *)malloc(egl_num_configs * sizeof(*egl_configs));
		if (egl_configs == NULL)
		{
			fprintf(stderr, "could not allocate memory for %d EGL configs\n", egl_num_configs);
			return egl_conf;
		}

		rc = eglGetConfigs(egl_disp, egl_configs,
						   egl_num_configs, &egl_num_configs);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglGetConfigs");
			free(egl_configs);
			return egl_conf;
		}

		for (i = 0; i < egl_num_configs; i++)
		{
			if (egl_conf_attr.config_id != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_CONFIG_ID, &val);
				if (val == egl_conf_attr.config_id)
				{
					egl_conf = egl_configs[i];
					break;
				}
				else
				{
					continue;
				}
			}

			eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
			if (!(val & EGL_WINDOW_BIT))
			{
				continue;
			}

			eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
			if (!(val & EGL_OPENGL_ES2_BIT))
			{
				continue;
			}

			eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
			if (val == 0)
			{
				continue;
			}

			if (egl_conf_attr.red_size != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RED_SIZE, &val);
				if (val != egl_conf_attr.red_size)
				{
					continue;
				}
			}
			if (egl_conf_attr.green_size != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_GREEN_SIZE, &val);
				if (val != egl_conf_attr.green_size)
				{
					continue;
				}
			}
			if (egl_conf_attr.blue_size != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_BLUE_SIZE, &val);
				if (val != egl_conf_attr.blue_size)
				{
					continue;
				}
			}
			if (egl_conf_attr.alpha_size != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_ALPHA_SIZE, &val);
				if (val != egl_conf_attr.alpha_size)
				{
					continue;
				}
			}
			if (egl_conf_attr.samples != EGL_DONT_CARE)
			{
				eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SAMPLES, &val);
				if (val != egl_conf_attr.samples)
				{
					continue;
				}
			}

			egl_conf = egl_configs[i];
			break;
		}

		free(egl_configs);

		if (egl_conf == (EGLConfig)0)
		{
			fprintf(stderr, "eglChooseConfig: could not find a matching configuration\n");
		}

		return egl_conf;
	}

	int choose_format(EGLDisplay egl_disp, EGLConfig egl_conf)
	{
		EGLint buffer_bit_depth, alpha_bit_depth;
		eglGetConfigAttrib(egl_disp, egl_conf, EGL_BUFFER_SIZE, &buffer_bit_depth);
		eglGetConfigAttrib(egl_disp, egl_conf, EGL_ALPHA_SIZE, &alpha_bit_depth);
		switch (buffer_bit_depth)
		{
		case 32:
		{
			return SCREEN_FORMAT_RGBA8888;
		}
		case 24:
		{
			return SCREEN_FORMAT_RGB888;
		}
		case 16:
		{
			switch (alpha_bit_depth)
			{
			case 4:
			{
				return SCREEN_FORMAT_RGBA4444;
			}
			case 1:
			{
				return SCREEN_FORMAT_RGBA5551;
			}
			default:
			{
				return SCREEN_FORMAT_RGB565;
			}
			}
		}
		default:
		{
			return 0;
		}
		}
	}

	static uint8_t s_GLFWWindowCount = 0;

	QnxWindow::QnxWindow(const WindowProps &props)
	{
		Init(props);
	}

	QnxWindow::~QnxWindow()
	{
		Shutdown();
	}

	void QnxWindow::Init(const WindowProps &props)
	{
		m_Data.Title = props.Title;
		m_Data.Width = props.Width;
		m_Data.Height = props.Height;

		// HZ_CORE_INFO("Creating window {0} ({1}, {2})", props.Title, props.Width, props.Height);

		struct
		{
			EGLint client_version[2];
			EGLint none;
		} egl_ctx_attr = {
			.client_version = {EGL_CONTEXT_CLIENT_VERSION, 2},
			.none = EGL_NONE};

		struct
		{
			EGLint render_buffer[2];
			EGLint none;
		} egl_surf_attr = {
			.render_buffer = {EGL_RENDER_BUFFER, EGL_BACK_BUFFER},
			.none = EGL_NONE};

		// screen_context_t screen_ctx;
		// screen_window_t screen_win;
		// screen_event_t screen_ev;
		int usage = SCREEN_USAGE_OPENGL_ES2;
		int transp = SCREEN_TRANSPARENCY_NONE;
		int size[2] = {-1, -1};
		int pos[2] = {0, 0};
		int nbuffers = 2;
		int format;
		int val;
		EGLNativeDisplayType disp_id = EGL_DEFAULT_DISPLAY;
		EGLDisplay egl_disp;
		EGLConfig egl_conf;
		EGLSurface egl_surf;
		EGLContext egl_ctx;
		EGLint interval = 1;
		EGLBoolean verbose = EGL_FALSE;
		const char *conf_str = NULL;
		const char *tok;
		int rval = EXIT_FAILURE;
		// int pause = 0;
		int i;
		struct timespec to;
		uint64_t t, last_t;

		steady_clock::time_point t1 = steady_clock::now();

		float delta;
		last_t = 0;
		int frames = 0;
		int frame_limit_counter = -1;

		screen_display_t *screen_disp; /* native handle for our display */
		int screen_ndisplays;		   /* number of displays */
		const char *display = NULL;	   /* the display to create our window on */
		int screen_val;
		int pipeline = -1;
		int zorder = 0;
		int index_id = 0;

		for (i = 1; i < argc; i++)
		{
			if (strncmp(argv[i], "-config=", strlen("-config=")) == 0)
			{
				conf_str = argv[i] + strlen("-config=");
			}
			else if (strncmp(argv[i], "-size=", strlen("-size=")) == 0)
			{
				tok = argv[i] + strlen("-size=");
				size[0] = atoi(tok);
				while (*tok >= '0' && *tok <= '9')
				{
					tok++;
				}
				size[1] = atoi(tok + 1);
			}
			else if (strncmp(argv[i], "-pos=", strlen("-pos=")) == 0)
			{
				tok = argv[i] + strlen("-pos=");
				pos[0] = atoi(tok);
				while (*tok >= '0' && *tok <= '9' && *tok != '-')
				{
					tok++;
				}
				pos[1] = atoi(tok + 1);
			}
			else if (strncmp(argv[i], "-interval=", strlen("-interval=")) == 0)
			{
				interval = atoi(argv[i] + strlen("-interval="));
			}
			else if (strncmp(argv[i], "-index=", strlen("-index=")) == 0)
			{
				index_id = atoi(argv[i] + strlen("-index="));
			}
			else if (strncmp(argv[i], "-display=", strlen("-display=")) == 0)
			{
				display = argv[i] + strlen("-display=");
			}
			else if (strncmp(argv[i], "-transparency=", strlen("-transparency")) == 0)
			{
				tok = argv[i] + strlen("-transparency=");
				if (strcmp(tok, "none") == 0)
				{
					transp = SCREEN_TRANSPARENCY_NONE;
				}
				else if (strcmp(tok, "test") == 0)
				{
					transp = SCREEN_TRANSPARENCY_TEST;
				}
				else if (strcmp(tok, "src") == 0)
				{
					transp = SCREEN_TRANSPARENCY_SOURCE_OVER;
				}
				else
				{
					fprintf(stderr, "invalid transparency value: %s\n", tok);
				}
			}
			else if (strcmp(argv[i], "-single-buffer") == 0)
			{
				egl_surf_attr.render_buffer[1] = EGL_SINGLE_BUFFER;
			}
			else if (strcmp(argv[i], "-double-buffer") == 0)
			{
				egl_surf_attr.render_buffer[1] = EGL_BACK_BUFFER;
			}
			else if (strcmp(argv[i], "-verbose") == 0)
			{
				verbose = EGL_TRUE;
			}
			else if (strncmp(argv[i], "-frame-limit=", strlen("-frame-limit=")) == 0)
			{
				tok = argv[i] + strlen("-frame-limit=");
				frame_limit_counter = atoi(tok);
			}
			else if (strncmp(argv[i], "-pipeline=", strlen("-pipeline=")) == 0)
			{
				tok = argv[i] + strlen("-pipeline=");
				pipeline = atoi(tok);
			}
			else if (strncmp(argv[i], "-fg-alpha=", strlen("-fg-alpha=")) == 0)
			{
				tok = argv[i] + strlen("-fg-alpha=");
				fg_alpha = atof(tok);
			}
			else if (strncmp(argv[i], "-bg-alpha=", strlen("-bg-alpha=")) == 0)
			{
				tok = argv[i] + strlen("-bg-alpha=");
				bg_alpha = atof(tok);
			}
			else if (strncmp(argv[i], "-zorder=", strlen("-zorder=")) == 0)
			{
				tok = argv[i] + strlen("-zorder=");
				zorder = atoi(tok);
			}
			else
			{
				fprintf(stderr, "invalid command line option: %s\n", argv[i]);
			}
		}

		egl_disp = eglGetDisplay(disp_id);
		if (egl_disp == EGL_NO_DISPLAY)
		{
			egl_perror("eglGetDisplay");
			eglReleaseThread();
		}

		rc = eglInitialize(egl_disp, NULL, NULL);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglInitialize");
			eglTerminate(egl_disp);
		}

		egl_conf = choose_config(egl_disp, conf_str);
		if (egl_conf == (EGLConfig)0)
		{
			eglTerminate(egl_disp);
		}

		egl_ctx = eglCreateContext(egl_disp, egl_conf, EGL_NO_CONTEXT, (EGLint *)&egl_ctx_attr);
		if (egl_ctx == EGL_NO_CONTEXT)
		{
			egl_perror("eglCreateContext");
			eglTerminate(egl_disp);
		}

		if (verbose)
		{
			printf("EGL_VENDOR = %s\n", eglQueryString(egl_disp, EGL_VENDOR));
			printf("EGL_VERSION = %s\n", eglQueryString(egl_disp, EGL_VERSION));
			printf("EGL_CLIENT_APIS = %s\n", eglQueryString(egl_disp, EGL_CLIENT_APIS));
			printf("EGL_EXTENSIONS = %s\n\n", eglQueryString(egl_disp, EGL_EXTENSIONS));

			i = -1;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_CONFIG_ID, &i);
			printf("EGL_CONFIG_ID = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_RED_SIZE, &i);
			printf("EGL_RED_SIZE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_GREEN_SIZE, &i);
			printf("EGL_GREEN_SIZE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_BLUE_SIZE, &i);
			printf("EGL_BLUE_SIZE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_ALPHA_SIZE, &i);
			printf("EGL_ALPHA_SIZE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_DEPTH_SIZE, &i);
			printf("EGL_DEPTH_SIZE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_LEVEL, &i);
			printf("EGL_LEVEL = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_NATIVE_RENDERABLE, &i);
			printf("EGL_NATIVE_RENDERABLE = %s\n", i ? "EGL_TRUE" : "EGL_FALSE");

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_NATIVE_VISUAL_TYPE, &i);
			printf("EGL_NATIVE_VISUAL_TYPE = %d\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_RENDERABLE_TYPE, &i);
			printf("EGL_RENDERABLE_TYPE = 0x%04x\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_SURFACE_TYPE, &i);
			printf("EGL_SURFACE_TYPE = 0x%04x\n", i);

			i = 0;
			eglGetConfigAttrib(egl_disp, egl_conf, EGL_TRANSPARENT_TYPE, &i);
			if (i == EGL_TRANSPARENT_RGB)
			{
				printf("EGL_TRANSPARENT_TYPE = EGL_TRANSPARENT_RGB\n");

				i = 0;
				eglGetConfigAttrib(egl_disp, egl_conf, EGL_TRANSPARENT_RED_VALUE, &i);
				printf("EGL_TRANSPARENT_RED = 0x%02x\n", i);

				i = 0;
				eglGetConfigAttrib(egl_disp, egl_conf, EGL_TRANSPARENT_GREEN_VALUE, &i);
				printf("EGL_TRANSPARENT_GREEN = 0x%02x\n", i);

				i = 0;
				eglGetConfigAttrib(egl_disp, egl_conf, EGL_TRANSPARENT_BLUE_VALUE, &i);
				printf("EGL_TRANSPARENT_BLUE = 0x%02x\n\n", i);
			}
			else
			{
				printf("EGL_TRANSPARENT_TYPE = EGL_NONE\n\n");
			}
		}

		rc = screen_create_context(&screen_ctx, 0);
		if (rc)
		{
			fprintf(stderr, "iow_create_context failed with error %d (0x%08x)\n", rc, rc);
			eglDestroyContext(egl_disp, egl_ctx);
		}

		m_Window = rc = screen_create_window(&screen_win, screen_ctx);
		if (rc)
		{
			perror("screen_create_window");
			screen_destroy_context(screen_ctx);
		}

		printf("display start\n");

		if (display)
		{
			rc = screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT, &screen_ndisplays);
			if (rc)
			{
				perror("screen_get_context_property_iv(SCREEN_PROPERTY_DISPLAY_COUNT)");
				screen_destroy_window(screen_win);
			}

			screen_disp = (screen_display_t *)calloc(screen_ndisplays, sizeof(*screen_disp));
			if (screen_disp == NULL)
			{
				fprintf(stderr, "could not allocate memory for display list\n");
				screen_destroy_window(screen_win);
			}

			rc = screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS,
												(void **)screen_disp);
			if (rc)
			{
				perror("screen_get_context_property_ptr(SCREEN_PROPERTY_DISPLAYS)");
				free(screen_disp);
				screen_destroy_window(screen_win);
			}

			if (isdigit(*display))
			{
				int want_id = atoi(display);
				for (i = 0; i < screen_ndisplays; ++i)
				{
					int actual_id = 0; // invalid
					(void)screen_get_display_property_iv(screen_disp[i], SCREEN_PROPERTY_ID, &actual_id);
					if (want_id == actual_id)
					{
						break;
					}
				}
			}
			else
			{
				int type = -1;
				if (strcmp(display, "internal") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_INTERNAL;
				}
				else if (strcmp(display, "composite") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_COMPOSITE;
				}
				else if (strcmp(display, "svideo") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_SVIDEO;
				}
				else if (strcmp(display, "YPbPr") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_COMPONENT_YPbPr;
				}
				else if (strcmp(display, "rgb") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_COMPONENT_RGB;
				}
				else if (strcmp(display, "rgbhv") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_COMPONENT_RGBHV;
				}
				else if (strcmp(display, "dvi") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_DVI;
				}
				else if (strcmp(display, "hdmi") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_HDMI;
				}
				else if (strcmp(display, "other") == 0)
				{
					type = SCREEN_DISPLAY_TYPE_OTHER;
				}
				else
				{
					fprintf(stderr, "unknown display type %s\n", display);
					free(screen_disp);
					screen_destroy_window(screen_win);
				}
				for (i = 0; i < screen_ndisplays; i++)
				{
					screen_get_display_property_iv(screen_disp[i],
												   SCREEN_PROPERTY_TYPE, &screen_val);
					if (screen_val == type)
					{
						break;
					}
				}
			}

			i = index_id; // android=2
			// printf("screen_ndisplays=%d\n", screen_ndisplays);
			if (i >= screen_ndisplays)
			{
				fprintf(stderr, "couldn't find display %s\n", display);
				free(screen_disp);
				screen_destroy_window(screen_win);
			}

			rc = screen_set_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_disp[i]);
			if (rc)
			{
				perror("screen_set_window_property_ptr(SCREEN_PROPERTY_DISPLAY)");
				free(screen_disp);
				screen_destroy_window(screen_win);
			}

			free(screen_disp);
		}

		printf("display over\n");

		rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &zorder);
		if (rc)
		{
			perror("screen_set_window_property_iv(SCREEN_PROPERTY_ZORDER)");
			screen_destroy_window(screen_win);
		}

		format = choose_format(egl_disp, egl_conf);
		rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format);
		if (rc)
		{
			perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
			screen_destroy_window(screen_win);
		}

		if (pipeline != -1)
		{
			usage |= SCREEN_USAGE_OVERLAY;
		}
		rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
		if (rc)
		{
			perror("screen_set_window_property_iv");
			screen_destroy_window(screen_win);
		}

		if (size[0] > 0 && size[1] > 0)
		{
			rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SIZE, size);
			if (rc)
			{
				perror("screen_set_window_property_iv(SCREEN_PROPERTY_SIZE)");
				screen_destroy_window(screen_win);
			}
		}
		else
		{
			rc = screen_get_window_property_iv(screen_win, SCREEN_PROPERTY_SIZE, size);
			if (rc)
			{
				perror("screen_get_window_property_iv(SCREEN_PROPERTY_SIZE)");
				screen_destroy_window(screen_win);
			}
		}

		if (pos[0] != 0 || pos[1] != 0)
		{
			rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_POSITION, pos);
			if (rc)
			{
				perror("screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)");
				screen_destroy_window(screen_win);
			}
		}

		rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_TRANSPARENCY, &transp);
		if (rc)
		{
			perror("screen_set_window_property_iv(SCREEN_PROPERTY_TRANSPARENCY)");
			screen_destroy_window(screen_win);
		}

		rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SWAP_INTERVAL, &interval);
		if (rc)
		{
			perror("screen_set_window_property_iv(SCREEN_PROPERTY_SWAP_INTERVAL)");
			screen_destroy_window(screen_win);
		}

		if (pipeline != -1)
		{
			rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_PIPELINE, &pipeline);
			if (rc)
			{
				perror("screen_set_window_property_iv(SCREEN_PROPERTY_PIPELINE)");
				screen_destroy_window(screen_win);
			}
		}

		// Set ID string for debugging via /dev/screen.
		{
			const char *idstr = "DPY_CLUSTER";
			screen_set_window_property_cv(screen_win,
										  SCREEN_PROPERTY_ID_STRING, strlen(idstr), idstr);
		}

		rc = screen_create_window_buffers(screen_win, nbuffers);
		if (rc)
		{
			perror("screen_create_window_buffers");
			screen_destroy_window(screen_win);
		}

		egl_surf = eglCreateWindowSurface(egl_disp, egl_conf,
										  screen_win, (EGLint *)&egl_surf_attr);
		if (egl_surf == EGL_NO_SURFACE)
		{
			egl_perror("eglCreateWindowSurface");
			screen_destroy_window(screen_win);
		}

		rc = eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglMakeCurrent");
			eglDestroySurface(egl_disp, egl_surf);
		}

		rc = eglSwapInterval(egl_disp, interval);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglSwapInterval");
			eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		}

		rc = screen_create_event(&screen_ev);
		if (rc)
		{
			perror("screen_create_event");
			eglMakeCurrent(egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
		}

		if (verbose)
		{
			printf("GL_VENDOR = %s\n", (char *)glGetString(GL_VENDOR));
			printf("GL_RENDERER = %s\n", (char *)glGetString(GL_RENDERER));
			printf("GL_VERSION = %s\n", (char *)glGetString(GL_VERSION));
			printf("GL_EXTENSIONS = %s\n", (char *)glGetString(GL_EXTENSIONS));
		}

		++s_GLFWWindowCount;

		// m_Context = GraphicsContext::Create(m_Window);
		// m_Context->Init();

		rval = EXIT_SUCCESS;
		screen_destroy_event(screen_ev);

		SetVSync(true);
	}

	void QnxWindow::Shutdown()
	{
		--s_GLFWWindowCount;

		if (s_GLFWWindowCount == 0)
		{
			pthread_join(sound_thread, 0);
			sounds.clear();
		}
	}

	void QnxWindow::OnUpdate()
	{
		int val;
		while (!screen_get_event(screen_ctx, screen_ev, pause ? ~0 : 0))
		{
			rc = screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &val);
			if (rc || val == SCREEN_EVENT_NONE)
			{
				break;
			}
			switch (val)
			{
			case SCREEN_EVENT_CLOSE:
				rval = EXIT_SUCCESS;
				screen_destroy_event(screen_ev);
				break;
			case SCREEN_EVENT_POINTER:
				screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_BUTTONS, &val);
				if (val)
				{
					screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_POSITION, pos);
					if (pos[0] >= size[0] - exit_area_size &&
						pos[0] < size[0] &&
						pos[1] >= 0 &&
						pos[1] < exit_area_size)
					{
						rval = EXIT_SUCCESS;
						screen_destroy_event(screen_ev);
						break;
					}
				}
				break;
			case SCREEN_EVENT_KEYBOARD:
				//					screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_FLAGS, &val);
				//					if (val & KEY_DOWN) {
				//						screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_SYM, &val);
				//						switch (val) {
				//							case KEYCODE_ESCAPE:
				//								goto end;
				//							case KEYCODE_F:
				//								pause = !pause;
				//								break;
				//							default:
				//								break;
				//						}
				//					}
				break;
			case SCREEN_EVENT_MTOUCH_TOUCH:
				screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TOUCH_ID, &val);
				// printf("SCREEN_EVENT_MTOUCH_TOUCH SCREEN_PROPERTY_TOUCH_ID=%d\n", val);
				screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_POSITION, pos);
				// eventTouchApp(pos[0], pos[1]);
				break;
			case SCREEN_EVENT_MTOUCH_MOVE:
				screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_POSITION, pos);
				// eventMoveApp(pos[0], pos[1]);
				break;
			case SCREEN_EVENT_MTOUCH_RELEASE:
				screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_POSITION, pos);
				// eventReleaseApp(pos[0], pos[1]);
				break;
			}
			// printf("t val=%d,SCREEN_EVENT_POINTER=%d;SCREEN_EVENT_KEYBOARD=%d\n", val, SCREEN_EVENT_POINTER, SCREEN_EVENT_KEYBOARD);
			// eventApp(val);//key
		}
		rc = eglSwapBuffers(egl_disp, egl_surf);
		if (rc != EGL_TRUE)
		{
			egl_perror("eglSwapBuffers");
			break;
		}
		// m_Context->SwapBuffers();
	}

	void QnxWindow::SetVSync(bool enabled)
	{
		m_Data.VSync = enabled;
	}

	bool QnxWindow::IsVSync() const
	{
		return m_Data.VSync;
	}

#if defined(__QNXNTO__) && defined(__USESRCVERSION)
#include <sys/srcversion.h>
	__SRCVERSION("$URL: http://svn/product/branches/6.6.0/trunk/apps/screen/demos/gles2-gears/gles2-gears.c $ $Rev: 755191 $")
#endif

}
